﻿using ESRI.ArcGIS.AnalysisTools;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geoprocessor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AEFunction.UI
{
    public partial class frmClipByTiles : Form
    {
        SortedList<double, string> scaleList = new SortedList<double, string>();
        Dictionary<string, double> scaleDic = new Dictionary<string, double>();
        AxMapControl mapControl = null;
        public frmClipByTiles(AxMapControl mp)
        {
            InitializeComponent();
            mapControl = mp;
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog outputPathBrowseDlg = new FolderBrowserDialog();
            if (outputPathBrowseDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string strOutputPath = outputPathBrowseDlg.SelectedPath;
                if (strOutputPath.EndsWith("\\"))
                {
                    strOutputPath = strOutputPath.Remove(strOutputPath.Length - 1, 1);
                }
                txtOutputPath.Text = strOutputPath;
            }
        }

        private void btnAddNewScale_Click(object sender, EventArgs e)
        {

            //判断文本框是否为空，并通过正则表达式判断文本框中是否包含字符
            string strScale = txtNewScale.Text.Trim();
            if (strScale == "")
            {
                MessageBox.Show("请输入比例尺!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                txtNewScale.Focus();
                return;
            }

            //判断输入的比例尺格式是否符合标准
            string strRegExpress = @"^[1-9]+[ ]*:[ ]*\d+$|^\d+$";
            if (!System.Text.RegularExpressions.Regex.IsMatch(strScale, strRegExpress))
            {
                MessageBox.Show("输入的比例尺格式有误，请以正确的格式输入!\n示例：1:250000\n         1 : 250000\n         250000", "提示",
                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                txtNewScale.Focus();
                return;
            }

            //根据输入的比例尺是否包含分号进行分别处理
            bool isRightScaleString = false;
            double mapDis = 0.0; double realDis = 0.0;
            if (strScale.Contains(":"))
            {
                string[] strScaleArray = strScale.Split(':');
                if (double.TryParse(strScaleArray[0], out mapDis) && double.TryParse(strScaleArray[1], out realDis))
                {
                    //如果图面距离的值大于1，则需要将他的值换算为1
                    if (mapDis > 1)
                    {
                        realDis = realDis / mapDis;
                        mapDis = 1;
                    }
                    isRightScaleString = true;
                }
            }
            else
            {
                if (double.TryParse(strScale, out realDis))
                {
                    mapDis = 1;
                    isRightScaleString = true;
                }
            }

            if (isRightScaleString)
            {
                string strLsScaleString = mapDis + " : " + realDis.ToString("#,#");
                if (!scaleList.ContainsKey(realDis))
                {
                    scaleList.Add(realDis, strLsScaleString);
                    scaleDic.Add(strLsScaleString, realDis);
                    this.AddScale2ListBox();
                }
            }
            txtNewScale.Text = "";
            txtNewScale.Focus();
        }

        private void AddScale2ListBox()
        {
            lsOutputScales.Items.Clear();
            foreach (double dblScale in scaleList.Keys)
            {
                string strScaleString = scaleList[dblScale];
                lsOutputScales.Items.Add(strScaleString);
            }
        }
        private void btnRemoveScale_Click(object sender, EventArgs e)
        {
            if (lsOutputScales.SelectedIndex != -1)
            {
                string strScaleText = lsOutputScales.SelectedItem.ToString().Trim();
                lsOutputScales.Items.RemoveAt(lsOutputScales.SelectedIndex);
                if (scaleDic.ContainsKey(strScaleText))
                {
                    scaleList.Remove(scaleDic[strScaleText]);
                    scaleDic.Remove(strScaleText);
                }
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
        }

        private bool InitOutputPath(string strOutputPath)
        {
            if (!Directory.Exists(strOutputPath))
            {
                if (DialogResult.Yes == MessageBox.Show("地图输出路径不存在，是否立即创建新目录！", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                {
                    Directory.CreateDirectory(strOutputPath);
                }
                else
                {
                    return false;
                }
            }
            else if (Directory.GetFiles(strOutputPath).Length > 0 || Directory.GetDirectories(strOutputPath).Length > 0)
            {
                if (DialogResult.Yes == MessageBox.Show("地图输出路径“" + strOutputPath + "”不为空，需要清空目录下所有文件夹及文件。\n确定清空目录吗？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                {
                    try
                    {
                        Directory.Delete(strOutputPath, true);
                        Directory.CreateDirectory(strOutputPath);
                    }
                    catch (Exception)
                    {
                        //MessageBox.Show(ex.Message);
                    }
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
        private void btnOutput_Click(object sender, EventArgs e)
        {
            if (txtOutputPath.Text.Trim() == "")
            {
                MessageBox.Show("地图输出路径为空，选择输出位置！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                txtOutputPath.Focus();
                return;
            }
            //if (IsOutputPathContainChinese())
            //{
            //    MessageBox.Show("选择的路径中不能包含中文字符！");
            //    return;
            //}

            if (lsOutputScales.Items.Count == 0)
            {
                MessageBox.Show("请输入输出比例尺！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                txtNewScale.Focus();
                return;
            }

            //初始化目录
            string strOutputPath = txtOutputPath.Text.Trim();
            bool isInited = this.InitOutputPath(strOutputPath);

            if (!isInited)
            {
                MessageBox.Show("输出目录初始化失败！可能的原因\n   1. 输出目录不存在。\n   2. 输出目录不为空。", "输出错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            int tileWidth = 256;
            int tileHeight = 256;
            double nowScale = mapControl.ActiveView.FocusMap.MapScale;
            IEnvelope fullExtent = new EnvelopeClass();
            fullExtent = mapControl.get_Layer(1).AreaOfInterest;
            for (int i = 2; i < mapControl.LayerCount; i++)
            {
                fullExtent.Union(mapControl.get_Layer(i).AreaOfInterest);
            }

            IPoint pStart = fullExtent.UpperLeft;
            double Width = fullExtent.Width;
            double Height = fullExtent.Height;
            IFeatureLayer netLayer = mapControl.get_Layer(0) as IFeatureLayer;
            IFeatureClass netClass = netLayer.FeatureClass;
            IDataset dataset1 = (IDataset)netClass;
            IWorkspace workspace1 = dataset1.Workspace;
            //Cast for an IWorkspaceEdit  
            IWorkspaceEdit workspaceEdit1 = (IWorkspaceEdit)workspace1;
            //start an edit session and operation              
            workspaceEdit1.StartEditing(true);
            workspaceEdit1.StartEditOperation();
            foreach (var singlescale in scaleList)
            {
                //scalecount++;
                this.progressBar.Value = 0;
                //this.progressText = "共有" + scaleList.Count + "个比例尺，当前在第" + scalecount.ToString()
                //    + "个";
                Directory.CreateDirectory(txtOutputPath.Text + "\\" + singlescale.Key.ToString());
                double scale = singlescale.Key;
                mapControl.ActiveView.FocusMap.MapScale = scale;
                //IPoint p = new ESRI.ArcGIS.Geometry.PointClass();
                //p.X = pStart.X + mapControl.ActiveView.Extent.Width / 2;
                //p.Y = pStart.Y - mapControl.ActiveView.Extent.Height / 2;
                //IEnvelope tmpE = mapControl.ActiveView.Extent;
                //tmpE.CenterAt(p);
                //mapControl.ActiveView.Extent = tmpE;
                //mapControl.Refresh();

                ESRI.ArcGIS.esriSystem.tagRECT rect = new ESRI.ArcGIS.esriSystem.tagRECT();
                rect.bottom = 256;
                rect.left = 0;
                rect.right = 256;
                rect.top = 0;
                int StartPX = 0;
                int StartPY = 0;
                mapControl.ActiveView.ScreenDisplay.DisplayTransformation.FromMapPoint(pStart, out StartPX, out StartPY);
                IEnvelope mapRect = new EnvelopeClass();
                mapControl.ActiveView.ScreenDisplay.DisplayTransformation.TransformRect(mapRect, ref rect, 1);
                double WorldTileWidth = mapRect.Height;
                int ScreenTileWidth = 256;
                int nowCount = 0;
                double PixPerMeter = WorldTileWidth / ScreenTileWidth;
                int Hcount = (int)(Height / WorldTileWidth) + 1;
                int Wcount = (int)(Width / WorldTileWidth) + 1;

                Geoprocessor GP = new Geoprocessor();
                Clip clip = new Clip();
                GP.OverwriteOutput = true;

                DateTime t1 = DateTime.Now;
                for (int i = 0; i < Hcount; i++)
                {
                    for (int j = 0; j < Wcount; j++)
                    {
                        nowCount++;
                        int per = (int)((float)nowCount * 100 / (float)Hcount / (float)Wcount);
                        this.progressBar.Value = per;
                        //backgroundWorker1.ReportProgress(per);
                        this.progressText.Text = ((float)nowCount * 100 / (float)Hcount / (float)Wcount).ToString() + "%";

                        Ring ring1 = new RingClass();
                        IPoint p1 = new PointClass();
                        p1.PutCoords(pStart.X + j * WorldTileWidth, pStart.Y - i * WorldTileWidth);

                        IPoint p3 = new PointClass();
                        p3.PutCoords(pStart.X + (j + 1) * WorldTileWidth, pStart.Y - (i + 1) * WorldTileWidth);
                        IPoint p2 = new PointClass();
                        p2.PutCoords(p3.X,p1.Y);
                        IPoint p4 = new PointClass();
                        p4.PutCoords(p1.X, p3.Y);

                        ring1.AddPoint(p1);
                        ring1.AddPoint(p2);
                        ring1.AddPoint(p3);
                        ring1.AddPoint(p4);
                        ring1.AddPoint(p1);
                        IGeometryCollection pointPolygon = new PolygonClass();
                        pointPolygon.AddGeometry(ring1 as IGeometry);
                        IPolygon polyGonGeo = pointPolygon as IPolygon;
                        int featurecount = netClass.FeatureCount(null);
                        IFeature f = netClass.CreateFeature();
                        f.Shape = polyGonGeo;
                        f.Store();

                        #region 裁剪
                        for (int layerIndex = 1; layerIndex < mapControl.LayerCount; layerIndex++)
                        {
                            IFeatureLayer inFeatures = mapControl.get_Layer(layerIndex) as IFeatureLayer;
                            clip.in_features = inFeatures;
                            clip.clip_features = netLayer;
                            string layerName = inFeatures.Name;
                            layerName += "_" + i + "_" + j;
                            clip.out_feature_class = txtOutputPath.Text + "\\" + singlescale.Key.ToString() + "\\" + layerName + ".shp";
                            clip.cluster_tolerance = 0;
                            GP.Execute(clip, null);
                        }
                        #endregion

                        f.Delete();
                    }
                }
                DateTime t2 = DateTime.Now;
                nowCount = 0;
                for (int i = 0; i < Hcount; i++)
                {
                    for (int j = 0; j < Wcount; j++)
                    {
                        nowCount++;
                        int per = (int)((float)nowCount * 100 / (float)Hcount / (float)Wcount);
                        this.progressBar.Value = per;
                        //backgroundWorker1.ReportProgress(per);
                        this.progressText.Text = ((float)nowCount * 100 / (float)Hcount / (float)Wcount).ToString() + "%";

                        Ring ring1 = new RingClass();
                        IPoint p1 = new PointClass();
                        p1.PutCoords(pStart.X + j * WorldTileWidth, pStart.Y - i * WorldTileWidth);

                        IPoint p3 = new PointClass();
                        p3.PutCoords(pStart.X + (j + 1) * WorldTileWidth, pStart.Y - (i + 1) * WorldTileWidth);
                        IPoint p2 = new PointClass();
                        p2.PutCoords(p3.X, p1.Y);
                        IPoint p4 = new PointClass();
                        p4.PutCoords(p1.X, p3.Y);

                        ring1.AddPoint(p1);
                        ring1.AddPoint(p2);
                        ring1.AddPoint(p3);
                        ring1.AddPoint(p4);
                        ring1.AddPoint(p1);
                        IGeometryCollection pointPolygon = new PolygonClass();
                        pointPolygon.AddGeometry(ring1 as IGeometry);
                        IPolygon polyGonGeo = pointPolygon as IPolygon;
                        int featurecount = netClass.FeatureCount(null);
                        IFeature f = netClass.CreateFeature();
                        f.Shape = polyGonGeo;
                        f.set_Value(3, i);
                        f.set_Value(4, j);
                        f.Store();

                    }
                }


                workspaceEdit1.StopEditOperation();
                workspaceEdit1.StopEditing(true);
                IFeatureClassManage featureClassManage1 = (IFeatureClassManage)netLayer.FeatureClass;
                featureClassManage1.UpdateExtent();

                MessageBox.Show("聚类完成！所用时间为："+(t2-t1).ToString());

            }
        }
    }
}
